package to.aloen.spine;

import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public abstract class Spine {

    public static final SimpleStringProperty spineVersion = new SimpleStringProperty(null);

    public static final SimpleStringProperty projectName = new SimpleStringProperty(null);

    public static final SimpleStringProperty skin = new SimpleStringProperty(null);

    public static final SimpleStringProperty animate = new SimpleStringProperty(null);

    public static final SimpleBooleanProperty isLoop = new SimpleBooleanProperty(false);

    public static final SimpleBooleanProperty isPlay = new SimpleBooleanProperty(false);

    public static final SimpleBooleanProperty renderA = new SimpleBooleanProperty(true);

    public static final SimpleBooleanProperty batchA = new SimpleBooleanProperty(true);

    public static final SimpleFloatProperty scale = new SimpleFloatProperty(1.0f);

    public static final SimpleFloatProperty X = new SimpleFloatProperty(0.0f);

    public static final SimpleFloatProperty Y = new SimpleFloatProperty(-200f);

    public static final SimpleFloatProperty speed = new SimpleFloatProperty(1);

    public static final ObservableList<String> skinsList = FXCollections.observableArrayList();

    public static final ObservableList<String> animatesList = FXCollections.observableArrayList();
    // 进度设置
    public static final SimpleFloatProperty progress = new SimpleFloatProperty(0.0f);

    public static double percent = -1;

    public static FileHandle skelFile;

    public static FileHandle atlasFile;

    public static boolean isBinary = true;

    public static byte currentVersion = 0;

    ///////////////////////////////////
    protected OrthographicCamera camera;
    protected float trackTime;

    public abstract <T> T getAnimationState();

//    private ChangeListener<String> skinListener = (_1, _2, newValue) -> {
//        if (newValue == null)
//            skeleton.setSkin((Skin) null);
//        else
//            skeleton.setSkin(newValue);
//
//        skeleton.setSlotsToSetupPose();
//    };
//
//    private ChangeListener<String> animateListener = (_1, _2, newValue) -> {
//        if (newValue != null) {
//            state.setAnimation(0, newValue, isLoop.get());
//            isPlay.set(true);
//        } else {
//            state.setEmptyAnimation(0, 0);
//            isPlay.set(false);
//        }
//    };
//
//    private ChangeListener<Boolean> isLoopListener = (_1, _2, _3) -> {
//        if (isPlay.get()) {
//            isPlay.set(false);
//            isPlay.set(true);
//        }
//    };
//
//    private ChangeListener<Boolean> isPlayListener = (_1, oldValue, newValue) -> {
//        if (!newValue.equals(oldValue)) {
//            if (newValue) {
//                if (animate.get() == null)
//                    state.setAnimation(0, animatesList.getFirst(), isLoop.get());
//                else
//                    state.setAnimation(0, animate.get(), isLoop.get());
//
//                state.setTimeScale(speed.get());
//
//                if (percent < 1)
//                    state.getCurrent(0).setTrackTime(trackTime);
//            } else {
//                state.setTimeScale(0);
//                trackTime = state.getCurrent(0).getAnimationTime();
//            }
//        }
//    };
//
//    private ChangeListener<Number> scaleListener = (_1, _2, _3) -> {
//        Gdx.app.postRunnable(this::loadSkeleton);
//
//        if (animate.get() != null) {
//            state.setAnimation(0, animate.get(), isLoop.get());
//            isPlay.set(true);
//        }
//    };
//
//    private ChangeListener<Number> XListener = (_1, _2, _3) -> {
//        Gdx.app.postRunnable(this::loadSkeleton);
//
//        if (animate.get() != null) {
//            state.setAnimation(0, animate.get(), isLoop.get());
//            isPlay.set(true);
//        }
//    };
//
//    private ChangeListener<Number> YListener = (_1, _2, _3) -> {
//        Gdx.app.postRunnable(this::loadSkeleton);
//
//        if (animate.get() != null) {
//            state.setAnimation(0, animate.get(), isLoop.get());
//            isPlay.set(true);
//        }
//    };
//
//    private ChangeListener<Number> speedListener = (_1, _2, _3) -> state.setTimeScale(speed.get());
//
//    //////////////////////////////////////////////////////
//
//    private boolean loadSkeleton() {
//        try {
//            TextureAtlas.TextureAtlasData atlasData = new TextureAtlas.TextureAtlasData(atlasFile, atlasFile.parent(), false);
//            boolean linear = true;
//            for (int i = 0, n = atlasData.getPages().size; i < n; i++) {
//                TextureAtlas.TextureAtlasData.Page page = atlasData.getPages().get(i);
//                if (page.pma) {
//                    renderA.set(true);
//                    batchA.set(true);
//                }
//
//                if (page.minFilter != Texture.TextureFilter.Linear || page.magFilter != Texture.TextureFilter.Linear) {
//                    linear = false;
//                    break;
//                }
//            }
//
//            TextureAtlas atlas = getAtlas(linear, atlasData);
//
//            SkeletonData skeletonData;
//
//            if (isBinary) {
//                SkeletonBinary binary = new SkeletonBinary(atlas);
//                binary.setScale(scale.get());
//                skeletonData = binary.readSkeletonData(skelFile);
//            } else {
//                SkeletonJson json = new SkeletonJson(atlas);
//                json.setScale(scale.get());
//                skeletonData = json.readSkeletonData(skelFile);
//            }
//
//            if (skeletonData.getBones().size == 0) {
//                System.out.println("骨骼为空");
//                return false;
//            }
//
//            skeleton = new Skeleton(skeletonData);
//            skeleton.updateWorldTransform();
//            skeleton.setToSetupPose();
//            skeleton.setPosition(X.get(), Y.get());
//
//            state = new AnimationState(new AnimationStateData(skeletonData));
//            if (animate.get() == null)
//                state.setEmptyAnimation(0, 0);
//
//            spineVersion.set(skeletonData.getVersion());
//            projectName.set(skeletonData.getName());
//
//            if (skinsList.isEmpty())
//                lists(skeletonData.getSkins(), skeletonData.getAnimations());
//
//            return true;
//        } catch (Exception e) {
//            e.printStackTrace();
//            projectName.set("Failed to Load");
//            return false;
//        }
//    }
//    private void lists(Array<Skin> skins, Array<Animation> animations) {
//        for (Skin skin : skins)
//            skinsList.add(skin.getName());
//
//        for (Animation animation : animations)
//            animatesList.add(animation.getName());
//    }
    private TextureAtlas getAtlas(boolean linear, TextureAtlas.TextureAtlasData atlasData) {
        Texture.TextureFilter filter = linear ? Texture.TextureFilter.Linear : Texture.TextureFilter.Nearest;

        return new TextureAtlas(atlasData) {
            public AtlasRegion findRegion(String name) {
                AtlasRegion region = super.findRegion(name);

                if (region == null) {
                    FileHandle file = skelFile.sibling(name + ".png");

                    if (file.exists()) {
                        Texture texture = new Texture(file);
                        texture.setFilter(filter, filter);
                        region = new AtlasRegion(texture, 0, 0, texture.getWidth(), texture.getHeight());
                        region.name = name;
                    }
                }

                return region;
            }
        };
    }

    public void create() {

    }

    public abstract void render();

    public abstract void resize();

    public void reload() {
        skin.set(null);
        animate.set(null);
        skinsList.clear();
        animatesList.clear();
    }
}
